home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #2
/
Monster Media No. 2 (Monster Media)(1994).ISO
/
prog_gen
/
gcoope10.zip
/
GARBAGE.C
< prev
next >
Wrap
Text File
|
1994-07-22
|
5KB
|
207 lines
/*
garbage collection, makePerm, and s_ memory allocation shells,
for GCOOPE Version 1.0
by Brian Lee Price
Released as Public Domain July, 1994.
*/
#include <alloc.h>
#define __GARBAGE__
#include "gcstruct.h"
/* garbage collection static variables */
static int ErrMem=0;
static int Killed=0;
static int curNdx=0;
static int ageDcr=(int)MINDCRVAL;
static int shftVal=MAXSHIFTVAL;
static long timeVal=TIMVAL;
/* round-robin routine with adaptive features */
/*
FOR KERNEL USE ONLY.
This routine has two basic modes of operation, normally it
only examines a few objects each call and the age decrement value
is (usually) low. However in this basic mode, it is adaptive.
A time out of timeVal will slow down the routine, while an internal
out of memory error will speed up the routine. In this mode, the
collector will ignore any objects which are not of the current
process ID.
The second mode of operation goes into effect on an out of
memory condition. In this mode, it examines the maximum set number
of objects, decrementing the age by the maximum amount, and ignores
only a process ID of PERM_PROC_ID.
*/
static void garbage(void)
{
register int x;
register int locDcr;
int oldDcr;
int oldShft;
objectEntry * objEnt;
if(ErrMem)
{ /* on mem err, save norm parms, goto max vals */
oldDcr=ageDcr;
ageDcr=(int)MAXDCRVAL;
oldShft=shftVal;
shftVal=MINSHIFTVAL;
}
else if(--timeVal<=0) /* otherwise check for timer time out */
{
timeVal=TIMVAL;
ageDcr-=ageDcr>>2; /* reduce DCR by 25% */
if(ageDcr<MINDCRVAL)
{ /* if DCR bottomed out, check less often */
ageDcr=(int)(MINDCRVAL*3)/2;
shftVal+=(shftVal<(MAXSHIFTVAL))?1:0;
}
}
x=(objList.maxElems)>>shftVal;
x=(x<=0)?1:x;
if(NULL==(objEnt=objList.listPtr)) return;
for(locDcr=ageDcr;x>0;x--,curNdx++)
{
if(curNdx>=objList.maxElems) curNdx=0;
if(NULL==(objEnt[curNdx].objDef)) continue;
else if((curProcID!=objEnt[curNdx].procID && !ErrMem)
|| (objEnt[curNdx].procID==PERM_PROC_ID)) continue;
else if(objEnt[curNdx].lastAcc>locDcr) objEnt[curNdx].lastAcc-=locDcr;
else
{
g(Kill)((object) curNdx);
Killed=1;
}
}
if(ErrMem) /* if in memory error mode reset to normal parms */
{
if(Killed)
{
ageDcr=oldDcr+(oldDcr>>1); /* increase norm DCR by 50% */
shftVal=oldShft;
if(ageDcr>MAXDCRVAL)
{ /* if DCR MAXED, check more often */
ageDcr=(int)MAXDCRVAL/2;
shftVal-=(shftVal>MINSHIFTVAL)?1:0;
}
}
else
{
ageDcr=oldDcr;
shftVal=oldShft;
}
ErrMem=0;
}
}
/*
AVAILABLE FOR EXTERNAL USE.
This routine makes an object permanent with respect to the garbage
collector. After this call is made, g(Kill)(object,...) must be
called in order to remove the object from memory.
*/
stat makePerm(object instance)
{
objectEntry * objEnt;
if(instance<0) return FUNCOKAY;
if((NULL==(objEnt=getObject((tag) instance)))
|| (NULL==objEnt->objDef)) return FUNCFAIL;
objEnt->procID=PERM_PROC_ID;
return FUNCOKAY;
}
/*
FOR KERNEL USE ONLY.
This routine fakes a memory error if a list runs out of available
elements. Thus the garbage collector will kill off some of the older
instances to free up available slots.
*/
void outOfElems(void)
{
int x;
ErrMem=1;
Killed=0;
for(x=MAX_ERR_TRY;x>0 && !Killed;x--) garbage();
if(!Killed) g(Err)(Object,Object,gcerrmsg[ERR_OUT_OF_MEM]);
}
/*
AVAILABLE FOR EXTERNAL USE.
This is the standard library calloc shell, note that it works
directly with the garbage collector and as long as the default error
routine aborts the program, it NEVER returns NULL.
*/
void * s_calloc(unsigned nitems, unsigned size)
{
void * retVal;
garbage();
while(NULL==(retVal=calloc(nitems,size))) outOfElems();
return retVal;
}
/*
AVAILABLE FOR EXTERNAL USE.
This routine is here mostly for completeness, however note
that when upgrading to an aftermarker heap manager only the shell
routines in this module need to be modified.
*/
void s_free(void * block)
{
if(block!=NULL) free(block);
}
void * s_malloc(unsigned size)
{
void * retVal;
garbage();
while(NULL==(retVal=malloc(size))) outOfElems();
return retVal;
}
/*
AVAILABLE FOR EXTERNAL USE.
See s_calloc and s_free for notes.
*/
void * s_realloc(void * block, unsigned newSize)
{
void * retVal;
garbage();
while(NULL==(retVal=realloc(block,newSize))) outOfElems();
return retVal;
}